package testing

import (
	"fmt"
	"math/rand"
	"time"
)

// DataGenerator represents a test data generator
type DataGenerator struct {
	// rand is the random number generator
	rand *rand.Rand
}

// NewDataGenerator creates a new test data generator
func NewDataGenerator() *DataGenerator {
	return &DataGenerator{
		rand: rand.New(rand.NewSource(time.Now().UnixNano())),
	}
}

// GenerateIntegerData generates integer test data
func (g *DataGenerator) GenerateIntegerData(count int, min, max int) []interface{} {
	data := make([]interface{}, count)
	for i := 0; i < count; i++ {
		data[i] = map[string]interface{}{
			"id":    fmt.Sprintf("%d", i+1),
			"value": g.rand.Intn(max-min+1) + min,
		}
	}
	return data
}

// GenerateStringData generates string test data
func (g *DataGenerator) GenerateStringData(count int, length int) []interface{} {
	data := make([]interface{}, count)
	for i := 0; i < count; i++ {
		data[i] = map[string]interface{}{
			"id":    fmt.Sprintf("%d", i+1),
			"value": g.generateRandomString(length),
		}
	}
	return data
}

// GenerateUserData generates user test data
func (g *DataGenerator) GenerateUserData(count int) []interface{} {
	data := make([]interface{}, count)
	for i := 0; i < count; i++ {
		data[i] = map[string]interface{}{
			"id":       fmt.Sprintf("%d", i+1),
			"name":     g.generateRandomName(),
			"age":      g.rand.Intn(50) + 18,
			"email":    fmt.Sprintf("%s@example.com", g.generateRandomString(8)),
			"active":   g.rand.Intn(2) == 1,
			"created":  time.Now().Add(-time.Duration(g.rand.Intn(365)) * 24 * time.Hour).Format(time.RFC3339),
			"location": g.generateRandomLocation(),
		}
	}
	return data
}

// GenerateTransactionData generates transaction test data
func (g *DataGenerator) GenerateTransactionData(count int) []interface{} {
	data := make([]interface{}, count)
	for i := 0; i < count; i++ {
		data[i] = map[string]interface{}{
			"id":          fmt.Sprintf("txn-%d", i+1),
			"user_id":     fmt.Sprintf("%d", g.rand.Intn(100)+1),
			"amount":      float64(g.rand.Intn(10000)) / 100.0,
			"currency":    g.generateRandomCurrency(),
			"type":        g.generateRandomTransactionType(),
			"status":      g.generateRandomTransactionStatus(),
			"timestamp":   time.Now().Add(-time.Duration(g.rand.Intn(30)) * 24 * time.Hour).Format(time.RFC3339),
			"description": g.generateRandomTransactionDescription(),
		}
	}
	return data
}

// GenerateSensorData generates sensor test data
func (g *DataGenerator) GenerateSensorData(count int) []interface{} {
	data := make([]interface{}, count)
	for i := 0; i < count; i++ {
		data[i] = map[string]interface{}{
			"id":          fmt.Sprintf("sensor-%d", i+1),
			"device_id":   fmt.Sprintf("device-%d", g.rand.Intn(10)+1),
			"temperature": float64(g.rand.Intn(400)) / 10.0,
			"humidity":    float64(g.rand.Intn(1000)) / 10.0,
			"pressure":    float64(g.rand.Intn(10000)) / 10.0,
			"battery":     float64(g.rand.Intn(100)),
			"timestamp":   time.Now().Add(-time.Duration(g.rand.Intn(24)) * time.Hour).Format(time.RFC3339),
			"location":    g.generateRandomLocation(),
		}
	}
	return data
}

// generateRandomString generates a random string
func (g *DataGenerator) generateRandomString(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, length)
	for i := range b {
		b[i] = charset[g.rand.Intn(len(charset))]
	}
	return string(b)
}

// generateRandomName generates a random name
func (g *DataGenerator) generateRandomName() string {
	firstNames := []string{"John", "Jane", "Bob", "Alice", "Charlie", "David", "Eve", "Frank", "Grace", "Helen"}
	lastNames := []string{"Smith", "Johnson", "Williams", "Jones", "Brown", "Davis", "Miller", "Wilson", "Moore", "Taylor"}
	return firstNames[g.rand.Intn(len(firstNames))] + " " + lastNames[g.rand.Intn(len(lastNames))]
}

// generateRandomLocation generates a random location
func (g *DataGenerator) generateRandomLocation() map[string]interface{} {
	return map[string]interface{}{
		"latitude":  float64(g.rand.Intn(1800000)-900000) / 10000.0,
		"longitude": float64(g.rand.Intn(3600000)-1800000) / 10000.0,
	}
}

// generateRandomCurrency generates a random currency
func (g *DataGenerator) generateRandomCurrency() string {
	currencies := []string{"USD", "EUR", "GBP", "JPY", "CNY", "AUD", "CAD", "CHF", "HKD", "SGD"}
	return currencies[g.rand.Intn(len(currencies))]
}

// generateRandomTransactionType generates a random transaction type
func (g *DataGenerator) generateRandomTransactionType() string {
	types := []string{"payment", "refund", "deposit", "withdrawal", "transfer"}
	return types[g.rand.Intn(len(types))]
}

// generateRandomTransactionStatus generates a random transaction status
func (g *DataGenerator) generateRandomTransactionStatus() string {
	statuses := []string{"completed", "pending", "failed", "cancelled", "processing"}
	return statuses[g.rand.Intn(len(statuses))]
}

// generateRandomTransactionDescription generates a random transaction description
func (g *DataGenerator) generateRandomTransactionDescription() string {
	descriptions := []string{
		"Online purchase",
		"Subscription payment",
		"Utility bill",
		"Grocery shopping",
		"Restaurant payment",
		"Salary deposit",
		"ATM withdrawal",
		"Fund transfer",
		"Refund for returned item",
		"Service fee",
	}
	return descriptions[g.rand.Intn(len(descriptions))]
}
